package com.net.framework.help.widget.voice;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

import com.net.framework.help.recorder.AudioManage;
import com.net.framework.help.utils.DateUtil;
import com.net.framework.help.utils.PermissionUtil;
import com.net.framework.help.utils.UIUtils;

/**
 * 控制录音Button
 * 1、重写onTouchEvent；（changeState方法、wantToCancel方法、reset方法）；
 * 2、编写AudioDialogManage、并与该类AudioRecorderButton进行整合；
 * 3、编写AudioManage、并与该类AudioRecorderButton进行整合；
 */
public class AudioRecorderButton extends Button implements AudioManage.AudioStateListenter {
    public static final int PERMISSIONS_REQUEST_AUDIO = 0x2;
    /**
     * AudioRecorderButton的三个状态
     */
    public static final int STATE_NORMAL = 1;//默认状态
    public static final int STATE_RECORDERING = 2;//录音状态
    public static final int STATE_WANT_TO_CALCEL = 3;//取消状态
    public static final int STATE_AUDITION = 4;//试听状态
    private static final int DISTANCE_Y_CANCEL = 50;
    private int mCurState = STATE_NORMAL;// 当前录音状态
    private boolean isRecordering = false;// 是否已经开始录音
    private boolean mReady;// 是否触发onLongClick
    private AudioManage mAudioManage;

    private AudioRecordListener mListenter;

    private Activity activity;

    private boolean isEnabledAudition;//是否启用试听

    public boolean isEnabledAudition() {
        return isEnabledAudition;
    }

    /**
     * 设置是否启用试听
     *
     * @param enabledAudition true启用；默认不启用
     */
    public void setEnabledAudition(boolean enabledAudition) {
        isEnabledAudition = enabledAudition;
    }

    public void setAudioRecordListener(Activity activity, AudioRecordListener listenter) {
        this.activity = activity;
        this.mListenter = listenter;
    }

    //构造方法
    public AudioRecorderButton(Context context) {
        super(context, null);
    }

    public AudioRecorderButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        mAudioManage = AudioManage.getInstance();
        mAudioManage.setOnAudioStateListenter(this);
        setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (!isEnabled()) {
                    return false;
                }

                if (isAudioPermission()) {
                    try {
                        mReady = true;
                        // 真正显示应该在audio end prepared以后
                        mAudioManage.prepareAudio();
                    } catch (Exception e) {
                        mReady = false;
                        mListenter.onPermissionException();
                    }
                }
                return false;
            }
        });
    }


    public boolean isAudioPermission() {
        if (!PermissionUtil.hasSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO)) {
            String[] pp = new String[]{Manifest.permission.RECORD_AUDIO};
            ActivityCompat.requestPermissions(activity, pp, PERMISSIONS_REQUEST_AUDIO);
            return false;
        }
        return true;
    }

    /*
     * 复写onTouchEvent
     * @see android.widget.TextView#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        int action = event.getAction();   //获取当前Action
        //获取当前屏幕触摸点坐标位置
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN://按下
                if (null != mListenter) {
                    mListenter.onRecordPrepare();
                    mListenter.onClickDown(true);
                }
                break;
            case MotionEvent.ACTION_MOVE://移动
                // 已经开始录音状态时，根据X、Y的坐标，判断是否想要取消
                if (isRecordering) {
                    if (wantToCancel(x, y)) {
                        changeState(STATE_WANT_TO_CALCEL);
                    } else {
                        changeState(STATE_RECORDERING);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                mListenter.onClickDown(false);
                if (!mReady) {   //没有触发onLongClick
                    reset();
                    return super.onTouchEvent(event);
                }
                if (!isRecordering || mTime < 2000) {  //录音时间过短
                    if (mCurState != STATE_RECORDERING) {
                        UIUtils.shortToast("录音时间过短");
                    }
                    recordCancel();
                    reset();
                } else if (mCurState == STATE_RECORDERING) { //正常录制结束
                    // release
                    mAudioManage.release();
                    // callbackToAct
                    // 正常录制结束，回调录音时间和录音文件完整路径——在播放的时候需要使用
                    if (mListenter != null) {
                        mListenter.onRecordFinish(mTime, mAudioManage.getCurrentFilePath());
                    }
                    //判断是否要进入试听
                    if (isEnabledAudition) {//开启了试听
                        resetParam();
                        changeState(STATE_AUDITION);
                    } else {
                        //不试听
                        reset();
                    }
                } else if (mCurState == STATE_WANT_TO_CALCEL) {//取消录制
                    // cancel
                    recordCancel();
                    reset();
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    private boolean wantToCancel(int x, int y) {
        // 判断手指的滑动是否超出范围
        if (x < 0 || x > getWidth()) {
            return true;
        }
        if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
            return true;
        }
        return false;
    }

    public void recordCancel() {
        mAudioManage.cancel();
        mListenter.onRecordCancel();
    }

    /**
     * 恢复状态以及一些标志位;恢复成初始状态
     */
    private void reset() {
        resetParam();
        changeState(STATE_NORMAL);
    }

    private void resetParam() {
        isRecordering = false;
        mReady = false; //是否触发onLongClick
        mTime = 0;
    }

    /**
     * 删除录音
     */
    public void removeRecord() {
        mAudioManage.cancel();
        reset();
    }

//    /**
//     * @param x
//     * @param y
//     * @return
//     */
//    private boolean wantToCancel(int x, int y) {
//        // 判断手指的滑动是否超出范围
//        if (x < 0 || x > getWidth()) {
//            return true;
//        }
//        if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
//            return true;
//        }
//        return false;
//    }

    /**
     * 改变Button的背景和文本、展示不同状态的录音提示对话框
     *
     * @param state
     */
    private void changeState(int state) {
        if (mCurState != state) {
            mCurState = state;
            mListenter.onRecordState(state);
        }
    }

    /*
     * 实现“准备完毕”接口
     */
    @Override
    public void wellPrepared() {
        // TODO Auto-generated method stub
        mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
    }

    private static final int MSG_AUDIO_PREPARED = 0x110;   //准备完全
    private static final int MSG_VOICE_CHANGE = 0x111;     //声音改变

    /**
     * 接收子线程数据，并用此数据配合主线程更新UI
     * Handler运行在主线程（UI线程）中，它与子线程通过Message对象传递数据。
     * Handler接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象，把这些消息放入主线程队列中，配合主线程进行更新UI。
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_AUDIO_PREPARED://准备完成，开始录音
                    changeState(STATE_RECORDERING);
                    isRecordering = true;
                    //已经在录制，同时开启一个获取音量、并且计时的线程
                    new Thread(mGetVoiceLevelRunnable).start();
                    break;
                case MSG_VOICE_CHANGE://语音声音变化
                    mListenter.onRecordChange(DateUtil.formatRecordTime(mTime), mAudioManage.getVoiceLevel());
                    break;
            }
        }
    };

    private long mTime;  //开始录音时，计时；（在reset()中置空）
    /**
     * 获取音量大小的Runnable
     */
    private Runnable mGetVoiceLevelRunnable = new Runnable() {
        @Override
        public void run() {
            while (isRecordering) {
                try {
                    Thread.sleep(100);
                    mTime += 100;
                    mHandler.sendEmptyMessage(MSG_VOICE_CHANGE);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };


    public interface AudioRecordListener {
        void onRecordPrepare();

        /**
         * 手指是否按下
         */
        void onClickDown(boolean isDown);

        /**
         * 录音状态
         */
        void onRecordState(int state);

        /**
         * 录音变化
         *
         * @param recordTime 持续时间
         * @param voiceLevel 音量等级
         */
        void onRecordChange(String recordTime, float voiceLevel);


        /**
         * 录制完成
         *
         * @param seconds
         * @param audioFilePath
         */
        void onRecordFinish(long seconds, String audioFilePath);

        /**
         * 取消录制
         *
         * @return
         */
        void onRecordCancel();

        void onPermissionException();
    }
}
